package com.potevio.simulator.decode;


import com.potevio.simulator.util.CommFunction;
import com.potevio.simulator.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @Description:
 * @Date 2021/5/7  15:07
 * @Author zyd
 * @Version 1.0
 */
public class MsgDecoder extends ByteToMessageDecoder {
    private final static Logger LOGGER = LoggerFactory.getLogger(ByteToMessageDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> list) throws Exception {
        if (in.readableBytes() <= 2) {
            LOGGER.info("***********当前无数据报文，无需解码——msgLog***********");
            return;
        }
        // 可读长度必须大于基本长度
        if (in.readableBytes() > 4) {
            // 防止socket字节流攻击
            // 防止，服务端传来的数据过大，因为，太大的数据，是不合理的
            if (in.readableBytes() > 20480) {
                in.skipBytes(in.readableBytes());
            }

            // 记录包头开始的index
            int beginReader;    // 起始域
            int bodyLength;     // 长度域
            int len;
            Byte version;
            while (true) {
                // 获取包头开始的index
                beginReader = in.readerIndex();
                // 标记包头开始的index
                in.markReaderIndex();
                // 读信息头，找到正文的大小 4字节
                byte[] header = new byte[4];
                in.readBytes(header);
                // 包头起始域不是FA和F5时
                if (header[0] != -6 || header[1] != -11)// 用来当拆包时候剩余长度小于4的时候的保护
                {
                    byte[] da = new byte[1];
                    in.readerIndex(beginReader);
                    in.readBytes(da);
                    LOGGER.info("接收包开始，连接message——msgLog：{}", CommFunction.bytesToHexStr(da));
                    return;
                }
                // 获取长度域
                bodyLength = CommFunction.unsignByteToInt(header[2]);
                // 当可读的内容，是一个完整的消息的时候，跳出循环进入下一步处理
                if (in.readableBytes() >= bodyLength) {
                    len = in.readableBytes();
                    break;
                } else {
                    // 还原读指针
                    in.readerIndex(beginReader);
                    return;
                }
            }
            // 还原读指针
            in.readerIndex(beginReader);
            // 读取data数据
            //正常长度
            //12/28粘包注释掉	int dlen=4 + len;
            int dlen = 4 + bodyLength;

            in.readableBytes();
            byte[] data = new byte[dlen];
            in.readBytes(data);
            // 转为16进制字符串
            String checkSumHex = CommFunction.bytesToHexStr(data);
            LOGGER.info("接收服务端报文——msgLog：{}", checkSumHex);
            // 计算校验和域
            String checkSumDomain = HexUtil.getCheckSumDomain(checkSumHex.substring(10, checkSumHex.length() - 2));
            if (!checkSumDomain.equals(checkSumHex.substring(checkSumHex.length() - 2, checkSumHex.length()))) {
                LOGGER.error("校验和域不正确");
                System.out.println("报文："+checkSumHex);
                System.out.println("模拟器计算校验和域：checkSumDomain="+checkSumDomain+",接收到的报文校验和域=="+checkSumHex.substring(checkSumHex.length() - 2, checkSumHex.length()));
                //return;
            }
            LOGGER.info("-----------------------开始解析——msgLog-----------------------");
            ByteBuf msg = Unpooled.directBuffer(dlen);
            msg.writeBytes(data);
            list.add(msg);
        }
    }


}
